/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package analysis;

import core.Constants;
import java.math.BigDecimal;

/**
 *
 * @author Alexey Chirkov
 */
public class Analytic {

    private static double[] rootBessel1 = {0,
        3.83170597, 7.01558666, 10.17346813, 13.32369194, 16.47063005,
        19.61585851, 22.76008438, 25.90367209, 29.04682853, 32.18967991,
        35.33230755, 38.47476623, 41.61709421, 44.759319, 47.90146089,
        51.04353518, 54.18555364, 57.32752544, 60.46945784, 63.6113567};
    private static int N = 20;

    public static int getN() {
        return N;
    }

    public static void setN(int N) {
        Analytic.N = N;
    }

    public static double getRootBessel1(int i) {
        if (i >= 0 && i <= 20) {
            return rootBessel1[i];
        } else if (i > 20) {
            return (4 * i + 1) * Math.PI / 4;
        } else {
            return 0;
        }
    }

    public static double getEigenvalues(int i) {
        double temp = getRootBessel1(i) / Constants.getRadius();
        return temp * temp;
    }

    public static double J0(double x) {
        double res;
        if (x >= -3 && x <= 3) {
            res = 1 - 2.2499997 * Math.pow(x / 3, 2) + 1.2656208 * Math.pow(x / 3, 4)
                    - 0.3163866 * Math.pow(x / 3, 6) + 0.0444479 * Math.pow(x / 3, 8)
                    - 0.0039444 * Math.pow(x / 3, 10) + 0.0002100 * Math.pow(x / 3, 12);
        } else {
            double f0 = 0.79788456 - 0.00000077 * (3 / x)
                    - 0.00552740 * Math.pow(3 / x, 2) - 0.00009512 * Math.pow(3 / x, 3)
                    + 0.00137237 * Math.pow(3 / x, 4) - 0.00072805 * Math.pow(3 / x, 5)
                    + 0.00014476 * Math.pow(3 / x, 6);
            double t0 = x - 0.78539816 - 0.04166397 * (3 / x)
                    - 0.00003954 * Math.pow(3 / x, 2) + 0.00262573 * Math.pow(3 / x, 3)
                    - 0.00054125 * Math.pow(3 / x, 4) - 0.00029333 * Math.pow(3 / x, 5)
                    + 0.00013558 * Math.pow(3 / x, 6);
            res = Math.pow(x, -0.5) * f0 * Math.cos(t0);
        }
        return res;

    }

    public static double J1(double x) {

        double res;
        if (x >= -3 && x <= 3) {
            res = x * (0.5 - 0.56249985 * Math.pow(x / 3, 2)
                    + 0.21093573 * Math.pow(x / 3, 4) - 0.03954289 * Math.pow(x / 3, 6)
                    + 0.00443319 * Math.pow(x / 3, 8) - 0.00031761 * Math.pow(x / 3, 10)
                    + 0.00001109 * Math.pow(x / 3, 12));
        } else {
            double f1 = 0.79788456 + 0.00000156 * (3 / x)
                    + 0.01659667 * Math.pow(3 / x, 2) + 0.00017105 * Math.pow(3 / x, 3)
                    - 0.00249511 * Math.pow(3 / x, 4) + 0.00113653 * Math.pow(3 / x, 5)
                    - 0.00020033 * Math.pow(3 / x, 6);
            double t1 = x - 2.35619449 + 0.12499612 * (3 / x)
                    + 0.00005650 * Math.pow(3 / x, 2) - 0.00637879 * Math.pow(3 / x, 3)
                    + 0.00074348 * Math.pow(3 / x, 4) + 0.00079824 * Math.pow(3 / x, 5)
                    - 0.00029166 * Math.pow(3 / x, 6);
            res = Math.pow(x, -0.5) * f1 * Math.cos(t1);
        }
        return res;

    }

    public static int getTeoreticN(double eps) {
        double temp1 = Constants.getC() * Constants.getP() * Constants.getRadius() * Constants.getRadius() * Constants.getRadius();
        double a = Constants.getRadius() / 5;
        double temp2 = 5 * a * eps;

        double temp = temp1 / temp2;

        return (int) Math.round(temp) + 1;
    }

//++
    private static double getVal1(int i, double t) {
        if (i == 0) {
            double temp1=2*Constants.getAlpha()*Constants.getK();
            double temp2=Constants.getC()*Constants.getL();
            double temp=temp1/temp2;
            double a=1-Math.exp(temp*(-t));
            return a/temp;
        }
        double kc = Constants.getK() / Constants.getC();
        double al = Constants.getAlpha() / Constants.getL();
        kc = kc * getRootBessel1(i);
        al = al * kc;
        double temp = kc + al;
        double q = temp * t * (-1);
        double c = 1 - Math.exp(q);

        return c / temp;
    }
//++

    private static double getVal2(int i, double r) {
        double val = r / Constants.getRadius();
        val = val * getRootBessel1(i);
        double temp1 = J0(val);
        double temp2 = J0(getRootBessel1(i));
        temp2 = temp2 * temp2;
        return temp1 / temp2;
    }
//+

    private static double getVal3(int i) {

//        double temp = J1(getRootBessel1(i) / 5);
//        double in = (5 * Constants.getP()) / (getRootBessel1(i) * Math.PI);
//
//        return temp * in;
        if (i == 0) {
            return Constants.getP() / (2 * Math.PI);
        }
        double con = Constants.getRadius() * Constants.getRadius();
        con = con / (5 * getRootBessel1(i));
        double integral = J1(getRootBessel1(i) / 5);
        integral *= con;
        double intensity = Constants.getIntensity(0);
        return integral * intensity;
    }

    public static double getValueAt(double r, double t, double eps) {
        double result = Constants.getU0();
        double sum = 0;
        for (int i = 0; i <= N; i++) {
            double temp = getVal1(i, t) * getVal2(i, r) * getVal3(i);
            sum = sum + temp;

        }

        double temp1 = 2 * Constants.getBetta();
        sum = sum * temp1;
        double temp2 = Constants.getRadius() * Constants.getRadius();
        sum = sum / temp2;




        return result + sum;
    }

    public static void main(String[] args) {


//        for (int i = 0; i <= 180; i++) {
//            System.out.println(20-Analytic.getValueAt(4, i, 0.1));
//        }
        System.out.println(getVal1(0, 0));



    }

    public static int getPracticalN(double r, double t, int teoreticN, double eps) {
        int NP = teoreticN;
        Analytic.setN(NP);
        double valueT = Analytic.getValueAt(r, t, eps);
        double valueP = Analytic.getValueAt(r, t, eps);
        while (Math.abs(valueP - valueT) <= eps) {
            //System.out.println(valueP-valueT);
            NP--;
            if (NP == -1) {
                break;
            }
            Analytic.setN(NP);
            valueP = Analytic.getValueAt(r, t, eps);
        }
        return NP + 1;
    }
}
